package com.cinyi.ormlite.dao;

//import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import com.cinyi.ormlite.annotation.TField;
import com.cinyi.ormlite.core.BaseModel;
import com.cinyi.ormlite.core.IGenericDao;
import com.cinyi.ormlite.util.ReflectionUtils;

/**
 * @author penghui
 * @param <T>
 */
@SuppressWarnings("rawtypes")
public abstract class AbstractGenericDaoImpl<T extends BaseModel> implements IGenericDao<T> {
	
	private DatabaseAdapter databaseAdapter = null ;
	
	public AbstractGenericDaoImpl() {
	}
	
	public AbstractGenericDaoImpl(DatabaseAdapter adapter) {
		this.databaseAdapter = adapter ;
	}
	
	@Override
	public void save(T t) throws Exception {
		SQLModel model = databaseAdapter.buildInsertSQL(t) ;
		if(model.isValid()){
			databaseAdapter.executeSQL(model) ;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void saveOrUpdate(T t) throws Exception {
		Class<T> clazz = (Class<T>) t.getClass();
		Field[] fields = clazz.getDeclaredFields();
		
		Object idFieldValue = null ;
		
		for (Field field : fields) {
//			PropertyDescriptor pd = new PropertyDescriptor(field.getName(),t.getClass());
			if(field.isAnnotationPresent(TField.class)) {
				TField tfield = field.getAnnotation(TField.class);
				if(tfield.constrains().primaryKey()){
//					idFieldValue = pd.getReadMethod().invoke(t) ;
					idFieldValue = ReflectionUtils.getFieldValue(t, field.getName());
					continue ;
				}
			}
		}
		
		if(idFieldValue != null && findOne(idFieldValue, clazz) != null){
			update(t,true);
		}else{
			save(t);
		}
		
	}

	@Override
	public Integer update(T t) throws Exception {
		return update(t,false);
	}
	
	@Override
	public Integer update(T t,boolean ignoreNull) throws Exception { 
		SQLModel model = databaseAdapter.buildUpdateSQL(t, ignoreNull);
		if(model.isValid()){
			return databaseAdapter.executeSQL(model) ;
		}
		return 0 ;
	}
	

	@Override
	public Integer delete(Object id,Class<T> clazz) throws Exception {
		SQLModel model = databaseAdapter.buildDeleteSQL(id, clazz);
		if(model.isValid()){
			return databaseAdapter.executeSQL(model) ;
		}
		return 0 ;
		
	}
	@Override
	public T get(Object id,Class<T> clazz) throws Exception {
		return findOne(id,clazz);
	}

	@Override
	public T findOne(Object idValue,Class<T> clazz) throws Exception {
		SQLModel model = databaseAdapter.buildQuerySQL(idValue, clazz);
		if(model.isValid()){
			List<T> list = databaseAdapter.executeQuery(model) ;
			return list.size() > 0 ? list.get(0) : null;
		}
		return null ;
	}

	@Override
	public List<T> find(T t) throws Exception {
		SQLModel model = databaseAdapter.buildQuerySQL(t);
		if(model.isValid()){
			return databaseAdapter.executeQuery(model) ;
		}
		return null ;
	}
	
	@Override
	public List<T> findBySQL(Class<T> clazz , String sql) throws Exception {
		return findBySQL(clazz,sql,null);
	}
	
	@Override
	public List<T> findBySQL(Class<T> clazz , String sql,List<Object> params) throws Exception {
		return findBySQL(clazz,sql,params,0,0);
	}
	
	/**
	 * clazz 
	 * sql sql语句
	 * params 参数
	 * page 第几页
	 * rows 每页显示的记录数
	 */
	@Override
	public List<T> findBySQL(Class<T> clazz ,String sql,List<Object> params,int page,int rows) throws Exception {
		SQLModel model = databaseAdapter.buildQuerySQL(clazz, sql, params, page, rows);
		if(model.isValid()){
			return databaseAdapter.executeQuery(model) ;
		}
		return null ;
		
	}
	
	@Override
	public Long count(Map<String,Object> sqlWhereMap,Class<T> clazz) throws Exception {
		SQLModel model = databaseAdapter.buildCountSQL(sqlWhereMap, clazz);
		if(model.isValid()){
			return databaseAdapter.count(model) ;
		}
		return null ;
	}
	
	@Override
	public Long count(T t) throws Exception {
		SQLModel model = databaseAdapter.buildCountSQL(t);
		if(model.isValid()){
			return databaseAdapter.count(model) ;
		}
		return null ;
	}
	
	@Override
	public Long count(String sql,List<Object> params) throws Exception {
		SQLModel model = new SQLModel();
		model.setSql(sql);
		model.setData(params);
		model.setAction(DatabaseAdapter.ACT_QRY);
		return databaseAdapter.count(model) ;
	}

	@Override
	public Long count(String sql) throws Exception {
		return count(sql,null);
	}
	
	public DatabaseAdapter getDatabaseAdapter() {
		return databaseAdapter;
	}

	public void setDatabaseAdapter(DatabaseAdapter databaseAdapter) {
		this.databaseAdapter = databaseAdapter;
	}

	@Override
	public List<T> find(Class<T> clazz, Map<String, Object> sqlWhereMap,
			String orderby) throws Exception {
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Integer executeSQL(String sql, List<Object> params) throws Exception{
		SQLModel model = new SQLModel();
		model.setSql(sql);
		model.setData(params);
		model.setAction(DatabaseAdapter.ACT_NEW);
		return databaseAdapter.executeSQL(model) ;
	}
	
	
	@Override
	public void close() {
	}

}
